import { ref, nextTick } from 'vue'

interface FocusedCell {
  row: any
  field: string
  cellEl: HTMLElement
  rowEl: HTMLElement
  fieldEl: HTMLElement | null
}

export function useFocusManager(
  editHandler: {
    startEdit: (row: any, field?: string) => void
    endEdit: (row: any, field?: string) => void
    getRowKey: (row: any) => string
  },
  debounceTime = 50
) {
  const currentFocusedCell = ref<FocusedCell | null>(null)
  const focusTimeouts = new Map<string, NodeJS.Timeout>()

  // 获取行数据从DOM元素
  const getRowFromElement = (element: HTMLElement): any | null => {
    try {
      const rowEl = element.closest('[data-id]') as HTMLElement
      if (!rowEl) return null

      const dataId = rowEl.getAttribute('data-id')
      return { node_id: dataId } // 简化的行数据，实际使用时需要完整数据
    } catch (error) {
      console.warn('[FocusManager] 无法获取行数据:', error)
      return null
    }
  }

  // 获取字段名从DOM元素
  const getFieldFromElement = (element: HTMLElement): string | null => {
    try {
      const fieldEl = element.closest('[field]') as HTMLElement
      return fieldEl?.getAttribute('field') || null
    } catch (error) {
      return null
    }
  }

  // 获取单元格相关元素
  const getCellElements = (element: HTMLElement) => {
    const rowEl = element.closest('[data-id]') as HTMLElement
    const cellEl = element.closest('.virtual-table-cell') as HTMLElement
    const fieldEl = element.closest('[field]') as HTMLElement

    return { rowEl, cellEl, fieldEl }
  }

  // 处理焦点进入
  const handleFocusIn = (event: FocusEvent): void => {
    const target = event.target as HTMLElement
    if (!target) return

    try {
      const row = getRowFromElement(target)
      const field = getFieldFromElement(target)

      if (!row || !field) return

      const { rowEl, cellEl, fieldEl } = getCellElements(target)
      if (!rowEl || !cellEl) return

      // 清除之前单元格的保存定时器
      if (currentFocusedCell.value) {
        const prevKey = `${editHandler.getRowKey(currentFocusedCell.value.row)}_${
          currentFocusedCell.value.field
        }`
        const timeout = focusTimeouts.get(prevKey)
        if (timeout) {
          clearTimeout(timeout)
          focusTimeouts.delete(prevKey)
        }

        // 如果切换到不同的单元格，先保存之前的编辑
        const currentKey = `${editHandler.getRowKey(row)}_${field}`
        const prevCellKey = `${editHandler.getRowKey(currentFocusedCell.value.row)}_${
          currentFocusedCell.value.field
        }`

        if (currentKey !== prevCellKey) {
          editHandler.endEdit(currentFocusedCell.value.row, currentFocusedCell.value.field)
        }
      }

      // 更新当前焦点单元格
      currentFocusedCell.value = {
        row,
        field,
        cellEl,
        rowEl,
        fieldEl
      }

      // 开始编辑
      editHandler.startEdit(row, field)
    } catch (error) {
      console.warn('[FocusManager] 处理焦点进入失败:', error)
    }
  }

  // 处理焦点离开
  const handleFocusOut = (event: FocusEvent): void => {
    const target = event.target as HTMLElement
    const relatedTarget = event.relatedTarget as HTMLElement

    if (!target || !currentFocusedCell.value) return

    // 检查焦点是否移动到了同一个可编辑区域内的其他元素
    const currentEditableContainer = target.closest('[contenteditable="true"]')
    const nextEditableContainer = relatedTarget?.closest('[contenteditable="true"]')

    // 如果焦点仍在同一个 contenteditable 容器内，延迟处理
    if (currentEditableContainer && currentEditableContainer === nextEditableContainer) {
      const key = `${editHandler.getRowKey(currentFocusedCell.value.row)}_${
        currentFocusedCell.value.field
      }`

      // 清除之前的定时器
      const existingTimeout = focusTimeouts.get(key)
      if (existingTimeout) {
        clearTimeout(existingTimeout)
      }

      // 设置新的定时器
      const timeout = setTimeout(() => {
        if (currentFocusedCell.value) {
          editHandler.endEdit(currentFocusedCell.value.row, currentFocusedCell.value.field)
          currentFocusedCell.value = null
        }
        focusTimeouts.delete(key)
      }, debounceTime)

      focusTimeouts.set(key, timeout)
    } else {
      // 焦点完全离开，立即保存
      editHandler.endEdit(currentFocusedCell.value.row, currentFocusedCell.value.field)
      currentFocusedCell.value = null
    }
  }

  // 处理键盘事件
  const handleKeyDown = (event: KeyboardEvent): void => {
    if (!currentFocusedCell.value) return

    const { key, ctrlKey, metaKey } = event

    // Ctrl/Cmd + S 保存
    if ((ctrlKey || metaKey) && key === 's') {
      event.preventDefault()
      editHandler.endEdit(currentFocusedCell.value.row, currentFocusedCell.value.field, true)
    }

    // Escape 取消编辑
    if (key === 'Escape') {
      event.preventDefault()
      // 这里可以实现取消编辑的逻辑
      currentFocusedCell.value = null
    }

    // Enter 保存并移动到下一行
    if (key === 'Enter' && !event.shiftKey) {
      // 可以实现移动到下一行的逻辑
    }
  }

  // 手动设置焦点到指定单元格
  const focusCell = (row: any, field: string): void => {
    nextTick(() => {
      try {
        const rowKey = editHandler.getRowKey(row)
        const rowEl = document.querySelector(`[data-id="${rowKey}"]`)
        const fieldEl = rowEl?.querySelector(`[field="${field}"]`) as HTMLElement

        if (fieldEl) {
          fieldEl.focus()

          // 设置光标到内容末尾
          const range = document.createRange()
          const selection = window.getSelection()
          if (fieldEl.childNodes.length > 0) {
            range.selectNodeContents(fieldEl)
            range.collapse(false)
            selection?.removeAllRanges()
            selection?.addRange(range)
          }
        }
      } catch (error) {
        console.warn('[FocusManager] 设置焦点失败:', error)
      }
    })
  }

  // 获取当前编辑的单元格
  const getCurrentEditingCell = (): { row: any; field: string } | null => {
    return currentFocusedCell.value
      ? { row: currentFocusedCell.value.row, field: currentFocusedCell.value.field }
      : null
  }

  // 清理所有状态
  const cleanup = (): void => {
    currentFocusedCell.value = null
    focusTimeouts.forEach((timeout) => clearTimeout(timeout))
    focusTimeouts.clear()
  }

  return {
    handleFocusIn,
    handleFocusOut,
    handleKeyDown,
    focusCell,
    getCurrentEditingCell,
    cleanup
  }
}
